package cn.lopr.im.socketserver.service;

import cn.lopr.im.socketserver.bean.Message;
import cn.lopr.im.socketserver.constant.CallbackMessage;
import cn.lopr.im.socketserver.constant.Const;
import cn.lopr.im.socketserver.utils.DateUtils;
import cn.lopr.im.socketserver.utils.HttpUtil;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import org.java_websocket.WebSocket;
import org.java_websocket.handshake.ClientHandshake;
import org.java_websocket.server.WebSocketServer;

import java.io.IOException;
import java.lang.reflect.Type;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.util.Collection;
import java.util.HashMap;
import java.util.Map;

import static cn.lopr.im.socketserver.constant.Const.MessageType;

/**
 * @author shuangyang7
 * @date 2020/12/19 9:15
 */

public class IMSocketService extends WebSocketServer {

    HashMap<String, WebSocket> clients = new HashMap<>();

    public IMSocketService() throws IOException {
    }

    public IMSocketService(int port) throws IOException {
        super(new InetSocketAddress(port));
    }

    @Override
    public void onOpen(WebSocket webSocket, ClientHandshake clientHandshake) {
        System.out.println("IMSocketService.onOpen");
    }

    @Override
    public void onClose(WebSocket webSocket, int i, String s, boolean b) {
        System.out.println("用户" + getPhone(webSocket) + "已下线");
    }

    @Override
    public void onMessage(WebSocket webSocket, String s) {
        Message message = new Gson().fromJson(s, Message.class);

        MessageType type = MessageType.getTypeByCode(message.getType());

        assert type != null;

        switch (type) {
            case USER_ONLINE:
                clients.put(message.getFromUser(), webSocket);
                System.out.println(message.getFromUser() + "上线");
                break;
            case SEND_TO_USER:
            case SEND_ADD:
                sendToUser(message);
                break;
            default:
                break;
        }
        System.out.println("IMSocketService.onMessage: " + s);
    }

    @Override
    public void onMessage(WebSocket conn, ByteBuffer message) {
        super.onMessage(conn, message);
        System.out.println("IMSocketService.onMessage:" + message.toString());
    }

    @Override
    public void onError(WebSocket webSocket, Exception e) {
        e.printStackTrace();
    }

    @Override
    public void onStart() {
        System.out.println("IMSocketService.onStart");
    }

    public void sendToUser(Message message) {

        message.setDate(DateUtils.getTime());
        String json = new Gson().toJson(message);
        System.out.println(json);
        // 不在线
        if (clients.get(message.getToUser()) != null && isOnline(clients.get(message.getToUser()))) {
            clients.get(message.getToUser()).send(json);
            return;
        }
        //发送离线消息
        HashMap<String, String> map = new HashMap<>();
        map.put("type", message.getType() + "");
        map.put("fromUser", message.getFromUser());
        map.put("toUser", message.getToUser());
        map.put("date", DateUtils.getTime());
        map.put("msg", message.getMsg());
        map.put("isRead", "0");
        map.put("groupId", "0");
        //发送离线消息
        HttpUtil.doGetForResult(Const.SEND_OFFLINE_MESSAGE, map, data -> {
            Type jsonType = new TypeToken<CallbackMessage<?>>() {
            }.getType();
            System.out.println(data);
            CallbackMessage<?> callbackMessage = new Gson().fromJson(data, jsonType);
            //System.out.println(callbackMessage.toString());
        });
    }

    //判断用户是否在线
    public boolean isOnline(WebSocket webSocket) {
        boolean is = false;
        Collection<WebSocket> connections = getConnections();
        for (WebSocket socket : connections) {
            if (webSocket.equals(socket)) {
                is = true;
                break;
            }
        }

        return is;
    }

    //通过用户客户端对象找到对应的手机号
    public String getPhone(WebSocket webSocket) {
        String phone = null;
        for (String key : clients.keySet()) {
            WebSocket ws = clients.get(key);
            if (webSocket.equals(ws)) {
                phone = key;
                break;
            }
        }
        return phone;
    }

    public WebSocket getPhone(String phone) {
        if (clients.containsKey(phone)) {
            return clients.get(phone);
        }

        return null;
    }

    void sendToGroup(WebSocket webSocket, String message) {
        for (Map.Entry<String, WebSocket> entry : clients.entrySet()) {
            if (!webSocket.equals(entry.getValue())) {
                entry.getValue().send(message);
            }
        }
    }
}
